package com.stockz.equity.scanner;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import com.stockz.equity.manager.BarManager;
import com.stockz.equity.manager.ScripManager;
import com.stockz.equity.model.Bar;
import com.stockz.equity.model.Scrip;
import com.stockz.equity.scanner.callback.ScannerCallback;
import com.stockz.equity.scanner.model.ScannerEvent;
import com.stockz.equity.scanner.model.ScannerEvent.EventType;
import com.stockz.equity.scanner.screen.MatchStrengthCalculatingScreen;
import com.stockz.equity.scanner.screen.Screen;

@Component
public class ScannerImpl implements Scanner {

	@Autowired private ScripManager scripManager;
	@Autowired private BarManager barManager;
	private boolean cancelRequested = false;
	
	
	@Override
	public void cancel() {
		cancelRequested = true;
	}
	
	@Override
	public void scan(Screen<? extends Object> screen, 
			List<ScannerCallback> scannerCallbacks){
		if(screen == null || scannerCallbacks == null || scannerCallbacks.isEmpty()){
			return;
		}
		
		List<Scrip> scripList = scripManager.getAllScripList(barManager.getMaxBarDate());
		ScannerEvent event = new ScannerEvent();
		event.setScreen(screen);
		event.setTotalScripCount(scripList.size());
		event.setEventType(EventType.OnScanStart);
		for(ScannerCallback callback : scannerCallbacks){
			callback.onScannerEvent(event);
		}
		
		if(scripList != null && !scripList.isEmpty()){
			int totalMatchCount = 0;
			int totalSkippedCount = 0;
			for(int i = 0; i < scripList.size(); i++){
				
				if(cancelRequested){
					cancelRequested = false;
					event.setEventType(EventType.OnScanCancel);
					for(ScannerCallback callback : scannerCallbacks){
						callback.onScannerEvent(event);
					}
					break;
				}
				
				List<Bar> barList = barManager.getBarListByScripCode(
						scripList.get(i).getScripCode(),
						screen.getMandatorySpan()+1);
				
				if(barList.size() < screen.getMandatorySpan()){
					totalSkippedCount ++;
					event.setTotalSkippedCount(totalSkippedCount);
					event.setEventType(EventType.OnScripScanSkipped);
					for(ScannerCallback callback : scannerCallbacks){
						callback.onScannerEvent(event);
					}
					continue;
				}
								
				event.setScrip(scripList.get(i));
				event.setCurrentScripIndex(i);
				event.setBar(barList.get(0));
				event.setEventType(EventType.OnScripScanStart);
				for(ScannerCallback callback : scannerCallbacks){
					callback.onScannerEvent(event);
				}
				
				if(screen.isMatch(barList)){
					totalMatchCount++;
					event.setEventType(EventType.OnMatch);
					if(screen instanceof MatchStrengthCalculatingScreen){
						MatchStrengthCalculatingScreen<? extends Object> matchStrengthCalculatingScreen = 
							(MatchStrengthCalculatingScreen<? extends Object>)screen;
						event.setMatchStrength(matchStrengthCalculatingScreen.getMatchStrength());
					}
					for(ScannerCallback callback : scannerCallbacks){
						callback.onScannerEvent(event);
					}
					event.setTotalMatchCount(totalMatchCount);
				}else{
					event.setTotalMatchCount(totalMatchCount);
					event.setEventType(EventType.OnNotMatch);
					for(ScannerCallback callback : scannerCallbacks){
						callback.onScannerEvent(event);
					}
				}
				
				event.setEventType(EventType.OnScripScanEnd);
				for(ScannerCallback callback : scannerCallbacks){
					callback.onScannerEvent(event);
				}
				
			}
			
			event.setEventType(EventType.OnScanEnd);
			for(ScannerCallback callback : scannerCallbacks){
				callback.onScannerEvent(event);
			}
			
		}
	}
}
